
#ifndef SEPOLL_H_
#define SEPOLL_H_



#include <sys/epoll.h>
#include <netinet/in.h>
#include "sutil.h"


#ifdef __cplusplus
extern "C" {
#endif

int epollCreate( int _flags) {
	if( _flags != EPOLL_NONBLOCK && _flags != EPOLL_CLOEXEC) {
		_flags = EPOLL_CLOEXEC;
	}
	return epoll_create1(_flags | EPOLL_CLOEXEC);
}


int epollCtlAdd(int _epfd, int _fd, uint32_t _events) {
	if(_epfd <= 0 || _fd <= 0) {
		return (int)-1;
	}

	struct epoll_event ev;

	ev.data.fd = _fd;
	ev.events  = _events;

	return epoll_ctl(_epfd, EPOLL_CTL_ADD, _fd, &ev);

}


int epollCtlDel(int _epfd, int _fd) {

	if(_epfd <= 0 || _fd <= 0) {
		return (int)-1;
	}
	struct epoll_event ev;
	/* Actually the third parameter is useless But in kernel 2.6.9, there is
	 * a bug that requires the struct epoll_event* to be non-NULL.
	 */
	return epoll_ctl(_epfd, EPOLL_CTL_DEL, _fd, &ev);

}


int epollCtlMod(int _epfd, int _fd, uint32_t _events) {

	if(_epfd <= 0 || _fd <= 0) {
		return (int)-1;
	}

	struct epoll_event ev;

	ev.data.fd = _fd;
	ev.events  = _events;

	return epoll_ctl(_epfd, EPOLL_CTL_MOD, _fd, &ev);

}


int epollWait(int _epfd, struct epoll_event *_pEvents, int _maxNumEvent, int _timeout, __sigset_t *_pMask) {
	if(_epfd <= 0 || _pEvents <= 0 || _maxNumEvent <= 0) {
		return (int)-1;
	}

	if( _pMask == 0) {
		return epoll_wait( _epfd, _pEvents, _maxNumEvent, _timeout);
	} else {
		/* Both a file descriptor and a signal specified in _pMask can cause the
		 * epoll_pwait() return.
		 */
		return epoll_pwait( _epfd, _pEvents, _maxNumEvent, _timeout, _pMask);
	}
}

/**
 * We define the macros according to "man epoll_ctl". And additional enumeration other than the one below
 * can be found in /usr/include/x86_64-linux-gnu/sys/epoll.h.
 */
#define IS_CONN(_events,_n,_listen_fd)	(_events[_n].data.fd==_listen_fd)
#define IS_IN(_events,_n)		(_events[_n].events&EPOLLIN)
#define IS_OUT(_events,_n)		(_events[_n].events&EPOLLOUT)
#define IS_OOB(_events,_n)		(_events[_n].events&EPOLLPRI)

#ifdef EPOLLRDHUP
#define IS_HUP(_events,_n)		((_events[_n].events&EPOLLHUP)||(_events[_n].events&EPOLLRDHUP))
#else
#define IS_HUP(_events,_n)		(_events[_n].events&EPOLLHUP)
#endif

#define IS_MSG(_events,_n)		(_events[_n].events&EPOLLMSG)
#define IS_ERR(_events,_n)		(_events[_n].events&EPOLLERR)






#ifdef __cplusplus
}
#endif

#endif /* SEPOLL_H_ */
